package com.cheers.dao.impl;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.List;

import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

import com.cheers.dao.BaseDao;
import com.cheers.service.impl.AbstractServiceImpl;

public class AbstractDaoImpl extends HibernateDaoSupport implements BaseDao {

	protected final Logger logger = LoggerFactory.getLogger(AbstractServiceImpl.class);
	protected final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
	
	@Override
	public Object save(Object obj) throws Exception {
		getHibernateTemplate().saveOrUpdate(obj);
		return obj;
	}
	
	@SuppressWarnings("unchecked")
	@Override
	public <T> T load(Class<T> entityClass, Object entityId) throws Exception {
		return (T)getHibernateTemplate().load(entityClass, String.valueOf(entityId));
	}

	@SuppressWarnings("unchecked")
	@Override
	public <T> T get(Class<T> entityClass, Object entityId) throws Exception {
		return (T)getHibernateTemplate().get(entityClass, String.valueOf(entityId));
	}

	@Override
	public void remove(Object obj) throws Exception {
		getHibernateTemplate().delete(obj);
	}

	@SuppressWarnings("unchecked")
	@Override
	public <T> T findByHql(Class<T> entityClass, final String hql, final Object[] objs) throws Exception {
		return (T) getHibernateTemplate().execute(new HibernateCallback() {

			public Object doInHibernate(Session session)
					throws HibernateException, SQLException {
				Query query = session.createQuery(hql);
				if (objs != null) {
					for (int i = 0; i < objs.length; i++)
						query.setParameter(i, objs[i]);
				}
				return query.uniqueResult();
			}
			
		});
	}

	@SuppressWarnings("unchecked")
	@Override
	public <T> T findBySql(Class<T> entityClass, String sql, Object[] params)
			throws Exception {
		Query q = getSession().createSQLQuery(sql).addEntity(entityClass);
		if (params != null) {
			try {
				for (int i=0; i<params.length; i++) {
					q.setParameter(i, params[i]);
				}
			} catch (RuntimeException e) {
				throw e;
			}
		}
		if (null == q) return null;
		
		return (T)q.uniqueResult();
	}

	@SuppressWarnings("unchecked")
	@Override
	public <T> List<T> findListBySql(Class<T> entityClass, String sql,
			Object[] params) throws Exception {
		Query q = getSession().createSQLQuery(sql).addEntity(entityClass);
		if (params!=null && params.length>0) {
			try {
				for (int i=0; i<params.length; i++) {
					q.setParameter(i, params[i]);
				}
			} catch (RuntimeException e) {
				throw e;
			}
		}
		if (null == q) return null;
		return q.list();
	}

	@SuppressWarnings("unchecked")
	@Override
	public <T> List<T> findBySql(Class<T> entityClass, int firstindex,
			int maxresult, String sql, Object[] params) throws Exception {
		Query query = getSession().createSQLQuery(sql).addEntity(entityClass);
		if (params!=null && params.length>0) {
			try {
				for (int i=0; i<params.length; i++) {
					query.setParameter(i, params[i]);
				}
			} catch (RuntimeException e) {
				throw e;
			}
		}
		if (null == query) return null;
		query.setFirstResult(firstindex).setMaxResults(maxresult);
		return (List<T>)query.list();
	}

	@Override
	public List findBySql(int firstindex, int maxresult, String sql,
			Object[] params) throws Exception {
		Query query = getSession().createSQLQuery(sql);
		if (params!=null && params.length>0) {
			try {
				for (int i=0; i<params.length; i++) {
					query.setParameter(i, params[i]);
				}
			} catch (RuntimeException e) {
				throw e;
			}
		}
		if (null==query) return null;
		query.setFirstResult(firstindex).setMaxResults(maxresult);
		return query.list();
	}

	@Override
	public List findBySql(String sql, Object[] params) throws Exception {
		Query q = getSession().createSQLQuery(sql);
		if (params!=null && params.length>0) {
			try {
				for (int i=0; i<params.length; i++) {
					q.setParameter(i, params[i]);
				}
			} catch (RuntimeException e) {
				throw e;
			}
		}
		if (null == q) return null;
		return q.list();
	}

	@Override
	public int getCount(String sql, Object[] params) throws Exception {
		Query query = getSession().createSQLQuery(sql);
		if (params!=null && params.length>0) {
			try {
				for (int i=0; i<params.length; i++) {
					query.setParameter(i, params[i]);
				}
			} catch (RuntimeException e) {
				throw e;
			}
		}
		return ((BigInteger)query.uniqueResult()).intValue();
	}
	
	@Override
	public BigDecimal getSum(String sql, Object[] params) throws Exception {
		Query query = getSession().createSQLQuery(sql);
		if (params!=null && params.length>0) {
			try {
				for (int i=0; i<params.length; i++) {
					query.setParameter(i, params[i]);
				}
			} catch (RuntimeException e) {
				throw e;
			}
		}
		return (BigDecimal)query.uniqueResult();
	}

	@Override
	public Long executeUpdate(final String hql, final Object[] params) throws Exception {
		return (Long) getHibernateTemplate().execute(new HibernateCallback() {

			public Object doInHibernate(Session session)
					throws HibernateException, SQLException {
				Query query = session.createQuery(hql);
				query.setParameterList("params", params);
				Integer integer = Integer.valueOf(query.executeUpdate());
				return new Long(integer.intValue());
			}

		});
	}

}
